/** Part of Zombie Navigator
	Copyright © 2016  Zombie Navigator Developers
	
	@file
	@module
	@license AGPL-3.0+
	
*/ 'use strict';


/*
	Public API
	NOTE: This is a pseudo-module used by a Zombie script, which runs
	unprivileged. It should be stable as well as secure.
*/


/* Used modules */
const _pTimer = require('../../platform/timer');


/* Zombie API */
Object.freeze(Promise); // it doesn't harm to be paranoia

/**
	Get the module object for use in a Zombie script
	@public
*/
const getZombieAPI = scriptURI => {
	return {
		__proto__: null
		,
		/**
			ES6 implementation for ES7 async functions
			@public
			@param {function} genFunction - generator (coroutine)
			@returns {Promise}
			@throws {TypeError}
		*/
		run (genFunction) {
			if ('function' != typeof genFunction) {
				throw new TypeError('Not a function');
			}
			
			let genObject = genFunction();
			
			if ('function' != typeof genObject.next) {
				throw new TypeError('Not a Iterator');
			}
			
			return new Promise(function (resolve, reject) {
				(function exec (promiseResult, isError) {
					try {
						let item;
						
						if (isError) {
							if ('function' != typeof genObject.throw) {
								// not a generator
								// throw globally?
								reject(e);
								
								throw e; // stop execution
							} else {
								// throw in the generator
								item = genObject.throw(promiseResult);
							}
						} else {
							item = genObject.next(promiseResult);
						}
						
						let throwException = e => {
							exec(e, true);
						};
						
						if (!item.done) {
							if (!(item.value instanceof Promise)) {
								throwException(new TypeError('Not a Promise'));
							} else {
								item.value
								.then(result => exec(result))
								.catch(throwException);
							}
						} else {
							// generator is completed
							resolve(item.value);
						}
					} catch (e) {
						reject(e);
					}
				}());
			});
		}
		,
		/**
			Asynchronous 'sleep'
			@public
			@param {number} s - number of seconds to sleep for
			@returns {Promise}
		*/
		delay (s) {
			return new Promise(function (resolve, reject) {
				const {setTimeout} = _pTimer;
				setTimeout(function () {
					resolve(true);
				}, (s * 1000) | 0);
			});
		}
	};
};


/* Exports */
exports.getZombieAPI = getZombieAPI;


// vim: ts=4 noet ai

